package algorithm;

import io.OutputWriter;

import java.io.IOException;
import java.util.Calendar;

import pac.SearchDatastructure;
import preprocessing.WindowingSystem;
import statistics.SignificanceHelper;
import datastructures.UserParameters;

public class MainClass {

	private static UserParameters userParameters;
	private static WindowingSystem windowingSystem;
	private static SignificanceHelper significanceHelper;
	private static SearchDatastructure searcher;
	private static OutputWriter outputter;
	
	public static void printWelcomeScreen() { 
		System.out.println("#******************************************************************");
		System.out.println("#\t SIXPAC : A search engine for genome-wide SNP-SNP synergy");
		System.out.println("#\t Version: 2.0");
		System.out.println("#\t Author: Snehit Prabhu");
		System.out.println("#\t Pe'er Lab of Computational Genetics");
		System.out.println("#\t Columbia University, New York");
		System.out.println("#******************************************************************");
	}
	
	public static void startTimer() {
		System.out.println();
		System.out.println("Started computation on : " + Calendar.getInstance().getTime());
		searcher.startTimeMs = System.currentTimeMillis( );	
	}
	
	public static void endTimer() {
		System.out.println("Finished on :\t" + Calendar.getInstance().getTime());		
		System.out.println("=========");
		System.out.println("Total processing time : " + (System.currentTimeMillis( ) - searcher.startTimeMs)/1000 + " seconds.");
		System.out.println("Output listed in " + searcher.userParams.getStage2Output());
		System.out.println("=========");
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {

		//1. Welcome the user.
		printWelcomeScreen();

		//2. Initialize these 2 data structures.
		userParameters = new UserParameters ( args );
		windowingSystem = new WindowingSystem ( );
		
		//4. Calculate the required significance thresholds.
		significanceHelper = new SignificanceHelper ( userParameters );

		//3. Initialize the main state and data containing class.
		searcher = new SearchDatastructure (userParameters, windowingSystem, significanceHelper);

		//5. Outputwriter
		outputter = new OutputWriter(searcher, significanceHelper);
		
		//6. Do your job
		startTimer();
		
		if( userParameters.getMode().equals("complete") ) {
			System.out.println("Performing a complete search ... ");
			try {
				CompleteSearch bruteforce = new CompleteSearch(searcher, outputter);
				bruteforce.doBruteForcePairwiseSearch();
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if (userParameters.getMode().equals("approx") ) {
			System.out.println("Performing an approximately complete search ... ");
			try {
				ApproxCompleteSearch approx = new ApproxCompleteSearch(searcher, outputter);
				approx.doApproximatePairwiseSearch();
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if (userParameters.getMode().equals("pac") ) { 
			System.out.println("Performing a probably approximately complete search ... ");
			try {
				ProbApproxCompleteSearch approx = new ProbApproxCompleteSearch(searcher, outputter);
				approx.doPACSearch();
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if ( userParameters.getMode().equals("test") ) { 
			System.out.println( "Testing GPD-contrast of pairs listed in ... " + userParameters.getTestfilename() );
			try {
				TestCombinations tester = new TestCombinations(searcher, outputter);
				tester.getSignificance(userParameters.getTestfilename());
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if ( userParameters.getMode().equals("random") ) { 
			System.out.println( "Drawing " + userParameters.getNumberOfDraws() + " pairs.");
			try {
				RandomDraws randomDrawer = new RandomDraws(searcher, outputter);
				randomDrawer.drawPairs();
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if ( userParameters.getMode().equals("apply-map") ) { 
			System.out.println( "Clustering entries in " + userParameters.getTestfilename());
			try {
				ApplyMap geneticMapApplier = new ApplyMap(searcher, outputter);
				geneticMapApplier.applyGeneticMap( );
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		else if ( userParameters.getMode().equals("cluster") ) { 
			System.out.println( "Clustering entries in " + userParameters.getTestfilename());
			try {
				ClusterResults clusteringTool = new ClusterResults(searcher, outputter);
				clusteringTool.doClustering( userParameters.getTestfilename() );
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
		
		//print important info and finish.
		endTimer();
		return;
		
	}
	
}
